using System;
using System.Collections.Generic;
using System.Data;
using System.Threading;
using Oracle.ManagedDataAccess.Client;
using OracleInternal.Common;
using OracleInternal.ConnectionPool;
using OracleInternal.ServiceObjects;

namespace OracleInternal.Sharding
{
	internal class ShardRoutingCache
	{
		private ShardingMetadata shardingMetadata;

		private ShardingRangeMap shardingRangeMap;

		private Dictionary<RoutingKey, Chunk> keysToChunks;

		private Dictionary<Chunk, HashSet<RoutingKey>> chunksToKeys;

		private Dictionary<Tuple<string, string>, HashSet<RoutingKey>> instsAndChunkNamesToKeys;

		private Dictionary<Tuple<string, string>, HashSet<Chunk>> instsAndChunkAbsNamesToChunks;

		private List<string> m_instances;

		private ReaderWriterLockSlim rwLock;

		private const int rwLockTimeout = 120000;

		internal ShardRoutingCache()
		{
			shardingMetadata = new ShardingMetadata();
			shardingRangeMap = new ShardingRangeMap(this);
			keysToChunks = new Dictionary<RoutingKey, Chunk>();
			chunksToKeys = new Dictionary<Chunk, HashSet<RoutingKey>>();
			instsAndChunkNamesToKeys = new Dictionary<Tuple<string, string>, HashSet<RoutingKey>>();
			instsAndChunkAbsNamesToChunks = new Dictionary<Tuple<string, string>, HashSet<Chunk>>();
			m_instances = new List<string>();
			rwLock = new ReaderWriterLockSlim();
		}

		internal void OnConnectionCreation(OracleConnectionImpl connImpl)
		{
			OracleConnection oracleConnection = new OracleConnection();
			oracleConnection.m_oracleConnectionImpl = connImpl;
			oracleConnection.m_connectionState = ConnectionState.Open;
			if (connImpl.m_pm.m_serverVersion != null)
			{
				oracleConnection.m_serverVersion = connImpl.m_pm.m_serverVersion;
			}
			else
			{
				oracleConnection.m_serverVersion = connImpl.GetServerVersion();
			}
			try
			{
				OnConnectionCreation(oracleConnection);
			}
			finally
			{
				oracleConnection.m_oracleConnectionImpl = null;
				oracleConnection.m_connectionState = ConnectionState.Closed;
				oracleConnection.m_serverVersion = null;
				oracleConnection.Dispose();
			}
		}

		internal void OnConnectionCreation(OracleConnection conn)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)288, OracleTraceClassName.ShardRoutingCache, OracleTraceFuncName.OnConnectionCreation);
			}
			if (rwLock.TryEnterUpgradeableReadLock(120000))
			{
				try
				{
					if (!m_instances.Contains(conn.InstanceName) && rwLock.TryEnterWriteLock(120000))
					{
						try
						{
							if (!m_instances.Contains(conn.InstanceName))
							{
								string[] array = conn.ServiceName.Split('%');
								string serviceName = ((array.Length == 2) ? array[1] : array[0]);
								FetchShardingMetadata(conn, serviceName);
								if (!BuildTopologyForInstance(conn, serviceName))
								{
									ClearCache();
									FetchShardingMetadata(conn, serviceName);
									BuildTopologyForInstance(conn, serviceName);
								}
								m_instances.Add(conn.InstanceName);
							}
						}
						finally
						{
							rwLock.ExitWriteLock();
						}
					}
				}
				finally
				{
					rwLock.ExitUpgradeableReadLock();
				}
			}
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)544, OracleTraceClassName.ShardRoutingCache, OracleTraceFuncName.OnConnectionCreation);
			}
		}

		internal void OnErrorInvalidateChunk(string instanceName, string chunkName)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)288, OracleTraceClassName.ShardRoutingCache, OracleTraceFuncName.OnErrorInvalidateChunk);
			}
			if (rwLock.TryEnterWriteLock(120000))
			{
				try
				{
					if (string.IsNullOrEmpty(chunkName))
					{
						return;
					}
					Chunk matchingChunk = GetMatchingChunk(instanceName, chunkName.ToUpper());
					if (matchingChunk == null)
					{
						return;
					}
					foreach (string item in new List<string>(matchingChunk.AllInstances))
					{
						matchingChunk.RemoveInstance(item);
						RemoveFromInstanceRelatedCaches(item, matchingChunk);
						m_instances.Remove(item);
					}
					Remove(matchingChunk);
				}
				finally
				{
					rwLock.ExitWriteLock();
				}
			}
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)544, OracleTraceClassName.ShardRoutingCache, OracleTraceFuncName.OnErrorInvalidateChunk);
			}
		}

		internal void OnErrorInvalidateChunkForInstance(string instanceName, string chunkName)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)288, OracleTraceClassName.ShardRoutingCache, OracleTraceFuncName.OnErrorInvalidateChunkForInstance);
			}
			if (rwLock.TryEnterWriteLock(120000))
			{
				try
				{
					if (string.IsNullOrEmpty(chunkName))
					{
						return;
					}
					Chunk matchingChunk = GetMatchingChunk(instanceName, chunkName.ToUpper());
					if (matchingChunk == null || !matchingChunk.HasInstance(instanceName))
					{
						return;
					}
					matchingChunk.RemoveInstance(instanceName);
					RemoveFromInstanceRelatedCaches(instanceName, matchingChunk);
					if (matchingChunk.AllInstances.Count == 0)
					{
						Remove(matchingChunk);
					}
				}
				finally
				{
					rwLock.ExitWriteLock();
				}
			}
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)544, OracleTraceClassName.ShardRoutingCache, OracleTraceFuncName.OnErrorInvalidateChunkForInstance);
			}
		}

		internal void OnAddChunk(OracleChunkEventArgs chunkEventArgs)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)288, OracleTraceClassName.ShardRoutingCache, OracleTraceFuncName.OnAddChunk);
			}
			if (rwLock.TryEnterWriteLock(120000))
			{
				try
				{
					if (shardingMetadata.ShardingType != ShardingType.LIST && shardingMetadata.ShardingType != ShardingType.RANGE)
					{
						return;
					}
					RoutingKey routingKey = DecodeUserShardingKeys(chunkEventArgs.ShardingKeys);
					Chunk chunk = Update(routingKey, chunkEventArgs.Chunk.ToUpper());
					if (chunk != null)
					{
						chunk.AddInstance(chunkEventArgs.Instance, chunkEventArgs.Priority, ChunkStatus.Up);
						AddToInstanceRelatedCaches(chunkEventArgs.Instance, chunk, routingKey);
					}
				}
				finally
				{
					rwLock.ExitWriteLock();
				}
			}
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)544, OracleTraceClassName.ShardRoutingCache, OracleTraceFuncName.OnAddChunk);
			}
		}

		internal void OnAddChunkValues(OracleChunkEventArgs chunkEventArgs)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)288, OracleTraceClassName.ShardRoutingCache, OracleTraceFuncName.OnAddChunkValues);
			}
			if (rwLock.TryEnterWriteLock(120000))
			{
				try
				{
					if (shardingMetadata.ShardingType != ShardingType.LIST)
					{
						return;
					}
					Chunk matchingChunk = GetMatchingChunk(chunkEventArgs.Instance, chunkEventArgs.Chunk.ToUpper());
					if (matchingChunk == null)
					{
						m_instances.Remove(chunkEventArgs.Instance);
						return;
					}
					int instancePriority = matchingChunk.GetInstancePriority(chunkEventArgs.Instance);
					ChunkStatus instanceStatus = matchingChunk.GetInstanceStatus(chunkEventArgs.Instance);
					RoutingKey routingKeysForVersionedChunk = GetRoutingKeysForVersionedChunk(chunkEventArgs.Instance, chunkEventArgs.Chunk.ToUpper());
					RoutingKey routingKey = DecodeUserShardingKeys(chunkEventArgs.ShardingKeys);
					List<OracleShardingKeyImpl> list = new List<OracleShardingKeyImpl>(routingKeysForVersionedChunk.ShardingKeys.Keys.Count + routingKey.ShardingKeys.Keys.Count);
					foreach (Tuple<OracleShardingKeyImpl, OracleShardingKeyImpl> key in routingKeysForVersionedChunk.ShardingKeys.Keys)
					{
						list.Add(key.Item1);
					}
					foreach (Tuple<OracleShardingKeyImpl, OracleShardingKeyImpl> key2 in routingKey.ShardingKeys.Keys)
					{
						list.Add(key2.Item1);
					}
					RoutingKey routingKey2 = new RoutingKey(new ListShardingKeys(list), routingKeysForVersionedChunk.SuperShardingKeys);
					matchingChunk.RemoveInstance(chunkEventArgs.Instance);
					RemoveFromInstanceRelatedCaches(chunkEventArgs.Instance, matchingChunk);
					if (matchingChunk.AllInstances.Count == 0)
					{
						Remove(matchingChunk);
					}
					Chunk chunk = Update(routingKey2, chunkEventArgs.Chunk.ToUpper());
					if (chunk != null)
					{
						chunk.AddInstance(chunkEventArgs.Instance, instancePriority, instanceStatus);
						AddToInstanceRelatedCaches(chunkEventArgs.Instance, chunk, routingKey2);
					}
				}
				finally
				{
					rwLock.ExitWriteLock();
				}
			}
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)544, OracleTraceClassName.ShardRoutingCache, OracleTraceFuncName.OnAddChunkValues);
			}
		}

		internal void OnDropChunk(OracleChunkEventArgs chunkEventArgs)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)288, OracleTraceClassName.ShardRoutingCache, OracleTraceFuncName.OnDropChunk);
			}
			if (rwLock.TryEnterWriteLock(120000))
			{
				try
				{
					if (shardingMetadata.ShardingType != ShardingType.LIST && shardingMetadata.ShardingType != ShardingType.RANGE)
					{
						return;
					}
					Chunk matchingChunk = GetMatchingChunk(chunkEventArgs.Instance, chunkEventArgs.Chunk.ToUpper());
					if (matchingChunk != null)
					{
						Remove(matchingChunk);
						matchingChunk.RemoveInstance(chunkEventArgs.Instance);
						RemoveFromInstanceRelatedCaches(chunkEventArgs.Instance, matchingChunk);
					}
				}
				finally
				{
					rwLock.ExitWriteLock();
				}
			}
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)544, OracleTraceClassName.ShardRoutingCache, OracleTraceFuncName.OnDropChunk);
			}
		}

		internal void OnDropChunkValues(OracleChunkEventArgs chunkEventArgs)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)288, OracleTraceClassName.ShardRoutingCache, OracleTraceFuncName.OnDropChunkValues);
			}
			if (rwLock.TryEnterWriteLock(120000))
			{
				try
				{
					if (shardingMetadata.ShardingType != ShardingType.LIST)
					{
						return;
					}
					RoutingKey item = DecodeUserShardingKeys(chunkEventArgs.ShardingKeys);
					try
					{
						Tuple<string, string> key = new Tuple<string, string>(chunkEventArgs.Instance, chunkEventArgs.Chunk.ToUpper());
						HashSet<RoutingKey> hashSet = instsAndChunkNamesToKeys[key];
						hashSet.Remove(item);
						Chunk matchingChunk = GetMatchingChunk(chunkEventArgs.Instance, chunkEventArgs.Chunk.ToUpper());
						Remove(matchingChunk);
						foreach (RoutingKey item2 in hashSet)
						{
							Put(item2, matchingChunk);
						}
					}
					catch (KeyNotFoundException)
					{
						m_instances.Remove(chunkEventArgs.Instance);
					}
				}
				finally
				{
					rwLock.ExitWriteLock();
				}
			}
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)544, OracleTraceClassName.ShardRoutingCache, OracleTraceFuncName.OnDropChunkValues);
			}
		}

		internal void OnMergeChunk(OracleChunkEventArgs chunkEventArgs)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)288, OracleTraceClassName.ShardRoutingCache, OracleTraceFuncName.OnMergeChunk);
			}
			if (rwLock.TryEnterWriteLock(120000))
			{
				try
				{
					if (shardingMetadata.ShardingType != ShardingType.LIST && shardingMetadata.ShardingType != ShardingType.RANGE)
					{
						return;
					}
					RoutingKey routingKeysForVersionedChunk = GetRoutingKeysForVersionedChunk(chunkEventArgs.Instance, chunkEventArgs.Chunk.ToUpper());
					RoutingKey routingKeysForVersionedChunk2 = GetRoutingKeysForVersionedChunk(chunkEventArgs.Instance, chunkEventArgs.ToChunk.ToUpper());
					Chunk matchingChunk = GetMatchingChunk(chunkEventArgs.Instance, chunkEventArgs.Chunk.ToUpper());
					Chunk matchingChunk2 = GetMatchingChunk(chunkEventArgs.Instance, chunkEventArgs.ToChunk.ToUpper());
					if (matchingChunk == null || matchingChunk2 == null)
					{
						if (matchingChunk != null)
						{
							matchingChunk.RemoveInstance(chunkEventArgs.Instance);
							RemoveFromInstanceRelatedCaches(chunkEventArgs.Instance, matchingChunk);
							if (matchingChunk.AllInstances.Count == 0)
							{
								Remove(matchingChunk);
							}
						}
						if (matchingChunk2 != null)
						{
							matchingChunk2.RemoveInstance(chunkEventArgs.Instance);
							RemoveFromInstanceRelatedCaches(chunkEventArgs.Instance, matchingChunk2);
							if (matchingChunk2.AllInstances.Count == 0)
							{
								Remove(matchingChunk2);
							}
						}
						m_instances.Remove(chunkEventArgs.Instance);
						return;
					}
					int instancePriority = matchingChunk.GetInstancePriority(chunkEventArgs.Instance);
					RoutingKey routingKey = null;
					if (ShardingType.LIST == shardingMetadata.ShardingType)
					{
						List<OracleShardingKeyImpl> list = new List<OracleShardingKeyImpl>(routingKeysForVersionedChunk.ShardingKeys.Keys.Count + routingKeysForVersionedChunk2.ShardingKeys.Keys.Count);
						foreach (Tuple<OracleShardingKeyImpl, OracleShardingKeyImpl> key in routingKeysForVersionedChunk.ShardingKeys.Keys)
						{
							list.Add(key.Item1);
						}
						foreach (Tuple<OracleShardingKeyImpl, OracleShardingKeyImpl> key2 in routingKeysForVersionedChunk2.ShardingKeys.Keys)
						{
							list.Add(key2.Item1);
						}
						routingKey = new RoutingKey(new ListShardingKeys(list), routingKeysForVersionedChunk.SuperShardingKeys);
					}
					else if (ShardingType.RANGE == shardingMetadata.ShardingType)
					{
						OracleShardingKeyImpl item = routingKeysForVersionedChunk.ShardingKeys.Keys[0].Item1;
						routingKey = new RoutingKey(new RangeShardingKeys(routingKeysForVersionedChunk2.ShardingKeys.Keys[0].Item2, item), routingKeysForVersionedChunk.SuperShardingKeys);
					}
					matchingChunk.RemoveInstance(chunkEventArgs.Instance);
					RemoveFromInstanceRelatedCaches(chunkEventArgs.Instance, matchingChunk);
					matchingChunk2.RemoveInstance(chunkEventArgs.Instance);
					RemoveFromInstanceRelatedCaches(chunkEventArgs.Instance, matchingChunk2);
					if (matchingChunk.AllInstances.Count == 0)
					{
						Remove(matchingChunk);
					}
					if (matchingChunk2.AllInstances.Count == 0)
					{
						Remove(matchingChunk2);
					}
					Chunk chunk = Update(routingKey, chunkEventArgs.ToChunk.ToUpper());
					if (chunk != null)
					{
						chunk.AddInstance(chunkEventArgs.Instance, instancePriority, ChunkStatus.Up);
						AddToInstanceRelatedCaches(chunkEventArgs.Instance, chunk, routingKey);
					}
				}
				finally
				{
					rwLock.ExitWriteLock();
				}
			}
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)544, OracleTraceClassName.ShardRoutingCache, OracleTraceFuncName.OnMergeChunk);
			}
		}

		internal void OnInvalidateChunk(OracleChunkEventArgs chunkEventArgs)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)288, OracleTraceClassName.ShardRoutingCache, OracleTraceFuncName.OnInvalidateChunk);
			}
			if (rwLock.TryEnterWriteLock(120000))
			{
				try
				{
					if (shardingMetadata.ShardingType != ShardingType.LIST && shardingMetadata.ShardingType != ShardingType.RANGE)
					{
						return;
					}
					Chunk matchingChunk = GetMatchingChunk(chunkEventArgs.Instance, chunkEventArgs.Chunk.ToUpper());
					if (matchingChunk != null)
					{
						Remove(matchingChunk);
						matchingChunk.RemoveInstance(chunkEventArgs.Instance);
						RemoveFromInstanceRelatedCaches(chunkEventArgs.Instance, matchingChunk);
					}
					m_instances.Remove(chunkEventArgs.Instance);
				}
				finally
				{
					rwLock.ExitWriteLock();
				}
			}
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)544, OracleTraceClassName.ShardRoutingCache, OracleTraceFuncName.OnInvalidateChunk);
			}
		}

		internal void OnMigrateChunk(OracleChunkEventArgs chunkEventArgs)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)288, OracleTraceClassName.ShardRoutingCache, OracleTraceFuncName.OnMigrateChunk);
			}
			if (rwLock.TryEnterWriteLock(120000))
			{
				try
				{
					if (string.IsNullOrEmpty(chunkEventArgs.Chunk) || (chunkEventArgs.Status != 0 && chunkEventArgs.Status != OracleChunkEventStatus.Up))
					{
						return;
					}
					if (chunkEventArgs.Status == OracleChunkEventStatus.ReadOnly)
					{
						Chunk matchingChunk = GetMatchingChunk(chunkEventArgs.Instance, chunkEventArgs.Chunk.ToUpper());
						if (matchingChunk == null || !matchingChunk.HasInstance(chunkEventArgs.Instance))
						{
							return;
						}
						matchingChunk.SetInstanceStatus(chunkEventArgs.Instance, ChunkStatus.ReadOnly);
					}
					else if (chunkEventArgs.Status == OracleChunkEventStatus.Up)
					{
						RoutingKey routingKeysForVersionedChunk = GetRoutingKeysForVersionedChunk(null, chunkEventArgs.Chunk.ToUpper());
						if (routingKeysForVersionedChunk == null)
						{
							m_instances.Remove(chunkEventArgs.Instance);
							return;
						}
						Chunk chunk = Get(routingKeysForVersionedChunk);
						if (chunk == null)
						{
							return;
						}
						chunk.AddInstance(chunkEventArgs.Instance, chunkEventArgs.Priority, ChunkStatus.Up);
						AddToInstanceRelatedCaches(chunkEventArgs.Instance, chunk, routingKeysForVersionedChunk);
					}
				}
				finally
				{
					rwLock.ExitWriteLock();
				}
			}
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)544, OracleTraceClassName.ShardRoutingCache, OracleTraceFuncName.OnMigrateChunk);
			}
		}

		internal void OnRemoveChunk(OracleChunkEventArgs chunkEventArgs)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)288, OracleTraceClassName.ShardRoutingCache, OracleTraceFuncName.OnRemoveChunk);
			}
			if (rwLock.TryEnterWriteLock(120000))
			{
				try
				{
					if (string.IsNullOrEmpty(chunkEventArgs.Chunk) || chunkEventArgs.Status != OracleChunkEventStatus.Down)
					{
						return;
					}
					Chunk matchingChunk = GetMatchingChunk(chunkEventArgs.Instance, chunkEventArgs.Chunk.ToUpper());
					if (matchingChunk == null || !matchingChunk.HasInstance(chunkEventArgs.Instance))
					{
						return;
					}
					matchingChunk.RemoveInstance(chunkEventArgs.Instance);
					RemoveFromInstanceRelatedCaches(chunkEventArgs.Instance, matchingChunk);
					if (matchingChunk.AllInstances.Count == 0)
					{
						Remove(matchingChunk);
					}
				}
				finally
				{
					rwLock.ExitWriteLock();
				}
			}
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)544, OracleTraceClassName.ShardRoutingCache, OracleTraceFuncName.OnRemoveChunk);
			}
		}

		internal void OnSplitChunk(OracleChunkEventArgs chunkEventArgs)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)288, OracleTraceClassName.ShardRoutingCache, OracleTraceFuncName.OnSplitChunk);
			}
			if (rwLock.TryEnterWriteLock(120000))
			{
				try
				{
					if (string.IsNullOrEmpty(chunkEventArgs.Chunk))
					{
						return;
					}
					Chunk matchingChunk = GetMatchingChunk(chunkEventArgs.Instance, chunkEventArgs.Chunk.ToUpper());
					if (matchingChunk == null)
					{
						m_instances.Remove(chunkEventArgs.Instance);
						return;
					}
					if (chunkEventArgs.Status == OracleChunkEventStatus.Split && matchingChunk.HasInstance(chunkEventArgs.Instance))
					{
						RoutingKey routingKey = null;
						RoutingKey routingKey2 = null;
						RoutingKey routingKeysForVersionedChunk = GetRoutingKeysForVersionedChunk(chunkEventArgs.Instance, chunkEventArgs.Chunk.ToUpper());
						int instancePriority = matchingChunk.GetInstancePriority(chunkEventArgs.Instance);
						ChunkStatus instanceStatus = matchingChunk.GetInstanceStatus(chunkEventArgs.Instance);
						if (shardingMetadata.ShardingType == ShardingType.HASH)
						{
							OracleShardingKeyImpl oracleShardingKeyImpl = new OracleShardingKeyImpl();
							oracleShardingKeyImpl.SetShardingKey(OracleDbType.Decimal, chunkEventArgs.Hash);
							oracleShardingKeyImpl.ShardKeyOraHash = chunkEventArgs.Hash;
							oracleShardingKeyImpl.Build();
							List<ShardingKeys> list = ((HashRangeShardingKeys)routingKeysForVersionedChunk.ShardingKeys).Split(oracleShardingKeyImpl);
							if (list.Count != 2)
							{
								Cleanup();
								return;
							}
							routingKey = new RoutingKey(list[0], routingKeysForVersionedChunk.SuperShardingKeys);
							routingKey2 = new RoutingKey(list[1], routingKeysForVersionedChunk.SuperShardingKeys);
						}
						else if (shardingMetadata.ShardingType == ShardingType.RANGE)
						{
							OracleShardingKeyImpl item = DecodeUserShardingKeys(chunkEventArgs.SplitVals).ShardingKeys.Keys[0].Item1;
							OracleShardingKeyImpl item2 = routingKeysForVersionedChunk.ShardingKeys.Keys[0].Item1;
							OracleShardingKeyImpl item3 = routingKeysForVersionedChunk.ShardingKeys.Keys[0].Item2;
							routingKey = new RoutingKey(new RangeShardingKeys(item, item2), routingKeysForVersionedChunk.SuperShardingKeys);
							routingKey2 = new RoutingKey(new RangeShardingKeys(item3, item), routingKeysForVersionedChunk.SuperShardingKeys);
						}
						else
						{
							if (shardingMetadata.ShardingType != ShardingType.LIST)
							{
								return;
							}
							routingKey2 = DecodeUserShardingKeys(chunkEventArgs.SplitVals);
							List<OracleShardingKeyImpl> list2 = new List<OracleShardingKeyImpl>();
							foreach (Tuple<OracleShardingKeyImpl, OracleShardingKeyImpl> key in routingKeysForVersionedChunk.ShardingKeys.Keys)
							{
								OracleShardingKeyImpl item4 = key.Item1;
								if (!routingKey2.ShardingKeys.Contains(item4))
								{
									list2.Add(item4);
								}
							}
							routingKey = new RoutingKey(new ListShardingKeys(list2), routingKeysForVersionedChunk.SuperShardingKeys);
						}
						matchingChunk.RemoveInstance(chunkEventArgs.Instance);
						RemoveFromInstanceRelatedCaches(chunkEventArgs.Instance, matchingChunk);
						if (matchingChunk.AllInstances.Count == 0)
						{
							Remove(matchingChunk);
						}
						Chunk chunk = Update(routingKey, chunkEventArgs.Chunk.ToUpper());
						if (chunk != null)
						{
							chunk.AddInstance(chunkEventArgs.Instance, instancePriority, instanceStatus);
							AddToInstanceRelatedCaches(chunkEventArgs.Instance, chunk, routingKey);
						}
						Chunk chunk2 = Update(routingKey2, chunkEventArgs.NewChunk.ToUpper());
						if (chunk2 != null)
						{
							chunk2.AddInstance(chunkEventArgs.Instance, instancePriority, instanceStatus);
							AddToInstanceRelatedCaches(chunkEventArgs.Instance, chunk2, routingKey2);
						}
					}
					Cleanup();
				}
				finally
				{
					rwLock.ExitWriteLock();
				}
			}
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)544, OracleTraceClassName.ShardRoutingCache, OracleTraceFuncName.OnSplitChunk);
			}
		}

		internal string[] GetAllPriorityInstances(OracleShardingKeyImpl superShardingKey, OracleShardingKeyImpl shardingKey, bool bReadOnlyChunkOK, ref string chunkName, ref string[] excludedInstances, ref InstanceInfo[] includedInstanceInfos)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)288, OracleTraceClassName.ShardRoutingCache, OracleTraceFuncName.GetAllPriorityInstances);
			}
			chunkName = null;
			excludedInstances = null;
			includedInstanceInfos = null;
			if (rwLock.TryEnterReadLock(120000))
			{
				try
				{
					if (!ValidateShardKeys(superShardingKey, shardingKey))
					{
						return null;
					}
					List<Chunk> chunks = GetChunks(superShardingKey, shardingKey);
					if (chunks == null)
					{
						return null;
					}
					List<InstanceInfo> list = new List<InstanceInfo>();
					List<InstanceInfo> list2 = new List<InstanceInfo>();
					List<string> list3 = new List<string>();
					List<string> list4 = new List<string>();
					foreach (Chunk item in chunks)
					{
						if (chunkName == null)
						{
							chunkName = item.AbsoluteName;
						}
						List<string> allHighestPriorityInstances = item.AllHighestPriorityInstances;
						if (allHighestPriorityInstances != null && allHighestPriorityInstances.Count > 0)
						{
							foreach (string item2 in allHighestPriorityInstances)
							{
								ChunkStatus instanceStatus = item.GetInstanceStatus(item2);
								int instancePriority = item.GetInstancePriority(item2);
								if (ChunkStatus.ReadOnly == instanceStatus)
								{
									list2.Add(new InstanceInfo(item2, item.AbsoluteName, instanceStatus, instancePriority));
									list4.Add(item2);
								}
								else
								{
									list.Add(new InstanceInfo(item2, item.AbsoluteName, instanceStatus, instancePriority));
									list3.Add(item2);
								}
							}
						}
					}
					string[] array = null;
					if (bReadOnlyChunkOK)
					{
						array = new string[list3.Count + list4.Count];
						excludedInstances = null;
						includedInstanceInfos = new InstanceInfo[list3.Count + list4.Count];
					}
					else
					{
						array = new string[list3.Count];
						excludedInstances = new string[list4.Count];
						includedInstanceInfos = new InstanceInfo[list3.Count];
					}
					list3.CopyTo(array);
					list.CopyTo(includedInstanceInfos);
					if (bReadOnlyChunkOK)
					{
						list4.CopyTo(array, list3.Count);
						list2.CopyTo(includedInstanceInfos, list.Count);
					}
					else
					{
						list4.CopyTo(excludedInstances);
					}
					return array;
				}
				finally
				{
					rwLock.ExitReadLock();
					if (ProviderConfig.m_bTraceLevelPrivate)
					{
						Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)544, OracleTraceClassName.ShardRoutingCache, OracleTraceFuncName.GetAllPriorityInstances);
					}
				}
			}
			return null;
		}

		internal List<string> GetAllInstances(OracleShardingKeyImpl superShardingKey, OracleShardingKeyImpl shardingKey)
		{
			if (rwLock.TryEnterReadLock(120000))
			{
				try
				{
					if (!ValidateShardKeys(superShardingKey, shardingKey))
					{
						return null;
					}
					List<string> list = new List<string>();
					List<Chunk> chunks = GetChunks(superShardingKey, shardingKey);
					if (chunks == null)
					{
						return list;
					}
					foreach (Chunk item in chunks)
					{
						HashSet<string> allInstances = item.AllInstances;
						if (allInstances != null && allInstances.Count > 0)
						{
							list.AddRange(allInstances);
						}
					}
					return list;
				}
				finally
				{
					rwLock.ExitReadLock();
				}
			}
			return null;
		}

		private bool ValidateShardKeys(OracleShardingKeyImpl superShardingKey, OracleShardingKeyImpl shardingKey)
		{
			if (shardingKey == null || !shardingKey.IsValid(shardingMetadata))
			{
				return false;
			}
			if (superShardingKey != null && !superShardingKey.IsValid(shardingMetadata))
			{
				return false;
			}
			return true;
		}

		internal void ClearCache()
		{
			shardingMetadata = new ShardingMetadata();
			shardingRangeMap.Clear();
			keysToChunks.Clear();
			chunksToKeys.Clear();
			instsAndChunkNamesToKeys.Clear();
			instsAndChunkAbsNamesToChunks.Clear();
			m_instances.Clear();
		}

		private List<Chunk> GetChunks(OracleShardingKeyImpl superShardingKey, OracleShardingKeyImpl shardingKey)
		{
			return shardingRangeMap.Get(superShardingKey, shardingKey);
		}

		internal long GetShardKeyOraHash(OracleShardingKeyImpl key)
		{
			if (shardingMetadata.ShardingType == ShardingType.HASH)
			{
				return key.ComputeShardKeyOraHash(shardingMetadata);
			}
			return OracleShardingKeyImpl.DEFAULT_ORA_HASH;
		}

		private HashSet<Chunk> GetChunks(string instanceName, string chunkAbsName)
		{
			Tuple<string, string> key = new Tuple<string, string>(instanceName, chunkAbsName);
			HashSet<Chunk> hashSet = null;
			try
			{
				return instsAndChunkAbsNamesToChunks[key];
			}
			catch (KeyNotFoundException)
			{
				return new HashSet<Chunk>();
			}
		}

		private HashSet<Chunk> GetChunks(string chunkAbsName)
		{
			HashSet<Chunk> hashSet = new HashSet<Chunk>();
			foreach (KeyValuePair<Tuple<string, string>, HashSet<Chunk>> instsAndChunkAbsNamesToChunk in instsAndChunkAbsNamesToChunks)
			{
				if (instsAndChunkAbsNamesToChunk.Key.Item2.Equals(chunkAbsName))
				{
					hashSet.UnionWith(instsAndChunkAbsNamesToChunk.Value);
				}
			}
			return hashSet;
		}

		private Chunk GetMatchingChunk(string instanceName, string chunkAbsName)
		{
			Chunk result = null;
			IEnumerator<Chunk> enumerator = ((instanceName == null) ? GetChunks(chunkAbsName) : GetChunks(instanceName, chunkAbsName)).GetEnumerator();
			if (enumerator.MoveNext())
			{
				result = enumerator.Current;
			}
			return result;
		}

		private bool BuildTopologyForInstance(OracleConnection connection, string serviceName)
		{
			bool result = true;
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)288, OracleTraceClassName.ShardRoutingCache, OracleTraceFuncName.BuildTopologyForInstance);
			}
			try
			{
				string instanceName = connection.InstanceName;
				foreach (Chunk.Metadata item in FetchInstanceChunksMetadata(connection, serviceName))
				{
					RoutingKey routingKey = MakeRoutingKey(item);
					string chunkName = item.ChunkName;
					if (ProviderConfig.m_bTraceLevelPrivate)
					{
						Trace.Write(OracleTraceLevel.Private, OracleTraceTag.Sharding, OracleTraceClassName.ShardRoutingCache, OracleTraceFuncName.BuildTopologyForInstance, $"Chunk = {item.ChunkName}, {routingKey.ToString()}, instance = {instanceName}, priority = {item.Priority}, status = {item.Status}");
					}
					Chunk chunk = Update(routingKey, chunkName);
					if (chunk != null)
					{
						chunk.AddInstance(instanceName, item.Priority, item.Status);
						chunk.Id = item.ChunkId;
						chunk.UniqueId = item.ChunkUniqueId;
						AddToInstanceRelatedCaches(instanceName, chunk, routingKey);
						if (ChunkStatus.ReadOnly == item.Status)
						{
							OracleConnectionDispenser<OraclePoolManager, OraclePool, OracleConnectionImpl>.m_sChunkUpEvents.CreateEvent(connection.DatabaseName, instanceName, chunk.AbsoluteName);
						}
						continue;
					}
					throw new Exception();
				}
			}
			catch (Exception)
			{
				result = false;
			}
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)544, OracleTraceClassName.ShardRoutingCache, OracleTraceFuncName.BuildTopologyForInstance);
			}
			return result;
		}

		private Chunk Update(RoutingKey routingKey, string chunkName)
		{
			if (routingKey == null || string.IsNullOrEmpty(chunkName))
			{
				return null;
			}
			Chunk chunk = new Chunk(chunkName);
			Chunk chunk2 = Get(routingKey);
			if (chunk2 != null && !chunk2.Name.Equals(chunkName))
			{
				return null;
			}
			if (chunk2 == null)
			{
				Put(routingKey, chunk);
				return chunk;
			}
			return chunk2;
		}

		private RoutingKey GetRoutingKeysForVersionedChunk(string instanceName, string chunkName)
		{
			try
			{
				Tuple<string, string> key = new Tuple<string, string>(instanceName, chunkName);
				HashSet<RoutingKey> hashSet = null;
				if (instanceName == null)
				{
					hashSet = new HashSet<RoutingKey>();
					foreach (KeyValuePair<Tuple<string, string>, HashSet<RoutingKey>> instsAndChunkNamesToKey in instsAndChunkNamesToKeys)
					{
						if (instsAndChunkNamesToKey.Key.Item2.Equals(chunkName))
						{
							hashSet.UnionWith(instsAndChunkNamesToKey.Value);
						}
					}
				}
				else
				{
					hashSet = instsAndChunkNamesToKeys[key];
				}
				RoutingKey result = null;
				IEnumerator<RoutingKey> enumerator2 = hashSet.GetEnumerator();
				if (enumerator2.MoveNext())
				{
					result = enumerator2.Current;
				}
				return result;
			}
			catch (KeyNotFoundException)
			{
				return null;
			}
		}

		private void Put(RoutingKey routingKey, Chunk chunk)
		{
			shardingRangeMap.Put(routingKey, chunk);
			keysToChunks.Add(routingKey, chunk);
			HashSet<RoutingKey> hashSet = null;
			try
			{
				hashSet = chunksToKeys[chunk];
			}
			catch (KeyNotFoundException)
			{
				hashSet = new HashSet<RoutingKey>();
				chunksToKeys[chunk] = hashSet;
			}
			hashSet.Add(routingKey);
		}

		private void AddToInstanceRelatedCaches(string instanceName, Chunk chunk, RoutingKey routingKey)
		{
			Tuple<string, string> key = new Tuple<string, string>(instanceName, chunk.Name);
			HashSet<RoutingKey> hashSet = null;
			try
			{
				hashSet = instsAndChunkNamesToKeys[key];
			}
			catch (KeyNotFoundException)
			{
				hashSet = new HashSet<RoutingKey>();
				instsAndChunkNamesToKeys[key] = hashSet;
			}
			hashSet.Add(routingKey);
			Tuple<string, string> key2 = new Tuple<string, string>(instanceName, chunk.AbsoluteName);
			HashSet<Chunk> hashSet2 = null;
			try
			{
				hashSet2 = instsAndChunkAbsNamesToChunks[key2];
			}
			catch (KeyNotFoundException)
			{
				hashSet2 = new HashSet<Chunk>();
				instsAndChunkAbsNamesToChunks[key2] = hashSet2;
			}
			hashSet2.Add(chunk);
		}

		private void PutNameToKey(string instanceName, Chunk chunk, RoutingKey routingKey)
		{
			Tuple<string, string> key = new Tuple<string, string>(instanceName, chunk.Name);
			HashSet<RoutingKey> hashSet = null;
			try
			{
				hashSet = instsAndChunkNamesToKeys[key];
			}
			catch (KeyNotFoundException)
			{
				hashSet = new HashSet<RoutingKey>();
				instsAndChunkNamesToKeys[key] = hashSet;
			}
			hashSet.Add(routingKey);
		}

		private void PutNameToChunk(string instanceName, Chunk chunk)
		{
			Tuple<string, string> key = new Tuple<string, string>(instanceName, chunk.AbsoluteName);
			HashSet<Chunk> hashSet = null;
			try
			{
				hashSet = instsAndChunkAbsNamesToChunks[key];
			}
			catch (KeyNotFoundException)
			{
				hashSet = new HashSet<Chunk>();
				instsAndChunkAbsNamesToChunks[key] = hashSet;
			}
			hashSet.Add(chunk);
		}

		private void Replace(RoutingKey routingKey, Chunk oldChunk, Chunk newChunk)
		{
			if (routingKey == null || oldChunk == null || newChunk == null)
			{
				throw new ArgumentNullException();
			}
			shardingRangeMap.Replace(routingKey, oldChunk, newChunk);
		}

		private Chunk Get(RoutingKey routingKey)
		{
			try
			{
				return keysToChunks[routingKey];
			}
			catch (KeyNotFoundException)
			{
				return null;
			}
		}

		private void Remove(Chunk chunk)
		{
			try
			{
				HashSet<RoutingKey> hashSet = chunksToKeys[chunk];
				foreach (RoutingKey item in hashSet)
				{
					shardingRangeMap.Remove(item, chunk);
					keysToChunks.Remove(item);
				}
				hashSet.Clear();
				chunksToKeys.Remove(chunk);
			}
			catch (KeyNotFoundException)
			{
			}
		}

		private void RemoveFromInstanceRelatedCaches(string instanceName, Chunk chunk)
		{
			RemoveNameToKey(instanceName, chunk);
			RemoveNameToChunk(instanceName, chunk);
		}

		private void RemoveNameToKey(string instanceName, Chunk chunk)
		{
			try
			{
				Tuple<string, string> key = new Tuple<string, string>(instanceName, chunk.Name);
				instsAndChunkNamesToKeys[key].Clear();
				instsAndChunkNamesToKeys.Remove(key);
			}
			catch (KeyNotFoundException)
			{
			}
		}

		private void RemoveNameToChunk(string instanceName, Chunk chunk)
		{
			try
			{
				Tuple<string, string> key = new Tuple<string, string>(instanceName, chunk.AbsoluteName);
				instsAndChunkAbsNamesToChunks[key].Clear();
				instsAndChunkAbsNamesToChunks.Remove(key);
			}
			catch (KeyNotFoundException)
			{
			}
		}

		private void Cleanup()
		{
		}

		private RoutingKey MakeRoutingKey(Chunk.Metadata chunkInfo)
		{
			List<OracleShardingKeyImpl> list = null;
			List<OracleShardingKeyImpl> list2 = null;
			ShardingType superShardingType = shardingMetadata.SuperShardingType;
			SuperShardingKeys superShardingKeys = null;
			switch (superShardingType)
			{
			case ShardingType.NONE:
				superShardingKeys = null;
				break;
			case ShardingType.LIST:
				list = OracleShardingKeyImpl.DecodeKeys(chunkInfo.GroupKeyHigh, shardingMetadata, isSuperKey: true, isKeyHigh: true);
				if (list == null)
				{
					return null;
				}
				superShardingKeys = new ListSuperShardingKeys(list);
				break;
			case ShardingType.RANGE:
				list = OracleShardingKeyImpl.DecodeKeys(chunkInfo.GroupKeyHigh, shardingMetadata, isSuperKey: true, isKeyHigh: true);
				list2 = OracleShardingKeyImpl.DecodeKeys(chunkInfo.GroupKeyLow, shardingMetadata, isSuperKey: true, isKeyHigh: false);
				if (list == null || list2 == null)
				{
					return null;
				}
				superShardingKeys = new RangeSuperShardingKeys(list[0], list2[0]);
				break;
			default:
				return null;
			}
			ShardingType shardingType = shardingMetadata.ShardingType;
			ShardingKeys shardingKeys = null;
			switch (shardingType)
			{
			case ShardingType.LIST:
				list = OracleShardingKeyImpl.DecodeKeys(chunkInfo.ShardKeyHigh, shardingMetadata, isSuperKey: false, isKeyHigh: true);
				if (list == null)
				{
					return null;
				}
				shardingKeys = new ListShardingKeys(list);
				break;
			case ShardingType.RANGE:
				list = OracleShardingKeyImpl.DecodeKeys(chunkInfo.ShardKeyHigh, shardingMetadata, isSuperKey: false, isKeyHigh: true);
				list2 = OracleShardingKeyImpl.DecodeKeys(chunkInfo.ShardKeyLow, shardingMetadata, isSuperKey: false, isKeyHigh: false);
				if (list == null || list2 == null)
				{
					return null;
				}
				shardingKeys = new RangeShardingKeys(list[0], list2[0]);
				break;
			case ShardingType.HASH:
				list = OracleShardingKeyImpl.DecodeKeys(chunkInfo.ShardKeyHigh, shardingMetadata, isSuperKey: false, isKeyHigh: true);
				list2 = OracleShardingKeyImpl.DecodeKeys(chunkInfo.ShardKeyLow, shardingMetadata, isSuperKey: false, isKeyHigh: false);
				if (list == null || list2 == null)
				{
					return null;
				}
				shardingKeys = new HashRangeShardingKeys(list[0], list2[0]);
				break;
			default:
				return null;
			}
			return new RoutingKey(shardingKeys, superShardingKeys);
		}

		private RoutingKey DecodeUserShardingKeys(string[] sKeys)
		{
			SuperShardingKeys superShardingKeys = null;
			ShardingType shardingType = shardingMetadata.ShardingType;
			List<byte[]> list = new List<byte[]>();
			foreach (string text in sKeys)
			{
				if (text.Equals("MAXVALUE", StringComparison.InvariantCultureIgnoreCase) || text.Equals("MINVALUE", StringComparison.InvariantCultureIgnoreCase))
				{
					list.Add(new byte[0]);
				}
				else
				{
					list.Add(Convert.FromBase64String(text));
				}
			}
			ShardingKeys keys;
			if (ShardingType.LIST == shardingType)
			{
				List<OracleShardingKeyImpl> list2 = OracleShardingKeyImpl.DecodeKeys(list, shardingMetadata, isSuperKey: false, isKeyHigh: false);
				if (list2 == null)
				{
					return null;
				}
				keys = new ListShardingKeys(list2);
			}
			else
			{
				if (ShardingType.RANGE != shardingType)
				{
					_ = 1;
					return null;
				}
				switch (list.Count)
				{
				case 1:
				{
					List<OracleShardingKeyImpl> list5 = OracleShardingKeyImpl.DecodeKeys(list, shardingMetadata, isSuperKey: false, isKeyHigh: false);
					if (list5 == null)
					{
						return null;
					}
					keys = new ListShardingKeys(list5);
					break;
				}
				case 2:
				{
					List<OracleShardingKeyImpl> list3 = OracleShardingKeyImpl.DecodeKeys(list.GetRange(0, 1), shardingMetadata, isSuperKey: false, isKeyHigh: false);
					List<OracleShardingKeyImpl> list4 = OracleShardingKeyImpl.DecodeKeys(list.GetRange(1, 1), shardingMetadata, isSuperKey: false, isKeyHigh: true);
					if (list3 == null || list4 == null || list3.Count == 0 || list4.Count == 0)
					{
						return null;
					}
					keys = new RangeShardingKeys(list4[0], list3[0]);
					break;
				}
				default:
					return null;
				}
			}
			return new RoutingKey(keys, superShardingKeys);
		}

		private List<Chunk.Metadata> FetchInstanceChunksMetadata(OracleConnection conn, string serviceName)
		{
			List<Chunk.Metadata> list = new List<Chunk.Metadata>();
			string text = "";
			text = ((int.Parse(conn.ServerVersion.Split('.')[0]) >= 19) ? "SELECT CHUNK_NAME, SHARD_KEY_LOW, SHARD_KEY_HIGH, GROUP_KEY_LOW , GROUP_KEY_HIGH, PRIORITY, CHUNK_ID, SHARD_NAME, CHUNK_UNIQUE_ID, STATE FROM LOCAL_CHUNKS WHERE TABFAM_ID=(SELECT TABFAM_ID FROM  LOCAL_TABLE_FAMILY_SERVICES WHERE SERVICE_NAME=:1) AND SHARD_KEY_LOW is not NULL AND SHARD_KEY_HIGH IS NOT NULL AND CHUNK_NAME is not NULL" : "SELECT CHUNK_NAME, SHARD_KEY_LOW, SHARD_KEY_HIGH, GROUP_KEY_LOW, \n                      GROUP_KEY_HIGH, PRIORITY, CHUNK_ID, SHARD_NAME, CHUNK_UNIQUE_ID, STATE  \n                      FROM LOCAL_CHUNKS \n                      WHERE SHARD_KEY_LOW is not NULL AND SHARD_KEY_HIGH IS NOT NULL AND CHUNK_NAME is not NULL");
			OracleCommand oracleCommand = null;
			OracleDataReader oracleDataReader = null;
			try
			{
				oracleCommand = new OracleCommand(text, conn);
				oracleCommand.Parameters.Add("prmServiceName", OracleDbType.Varchar2, serviceName, ParameterDirection.Input);
				oracleCommand.InitialLOBFetchSize = 2048;
				oracleDataReader = oracleCommand.ExecuteReader();
				while (oracleDataReader.Read())
				{
					Chunk.Metadata metadata = new Chunk.Metadata();
					metadata.ChunkName = (oracleDataReader.IsDBNull(0) ? null : oracleDataReader.GetString(0));
					metadata.ShardKeyLow = (oracleDataReader.IsDBNull(1) ? null : oracleDataReader.GetOracleBlob(1));
					metadata.ShardKeyHigh = (oracleDataReader.IsDBNull(2) ? null : oracleDataReader.GetOracleBlob(2));
					metadata.GroupKeyLow = (oracleDataReader.IsDBNull(3) ? null : oracleDataReader.GetOracleBlob(3));
					metadata.GroupKeyHigh = (oracleDataReader.IsDBNull(4) ? null : oracleDataReader.GetOracleBlob(4));
					metadata.Priority = ((!oracleDataReader.IsDBNull(5)) ? oracleDataReader.GetInt32(5) : 0);
					metadata.ChunkId = ((!oracleDataReader.IsDBNull(6)) ? oracleDataReader.GetInt32(6) : 0);
					metadata.ShardName = (oracleDataReader.IsDBNull(7) ? null : oracleDataReader.GetString(7));
					metadata.ChunkUniqueId = ((!oracleDataReader.IsDBNull(8)) ? oracleDataReader.GetInt32(8) : 0);
					metadata.Status = (ChunkStatus)((!oracleDataReader.IsDBNull(9)) ? oracleDataReader.GetInt32(9) : 0);
					list.Add(metadata);
				}
				return list;
			}
			catch (InvalidOperationException)
			{
				return list;
			}
			catch (Exception)
			{
				return list;
			}
			finally
			{
				if (oracleDataReader != null)
				{
					oracleDataReader.Dispose();
					oracleDataReader = null;
				}
				if (oracleCommand != null)
				{
					oracleCommand.Dispose();
					oracleCommand = null;
				}
			}
		}

		private void FetchShardingMetadata(OracleConnection conn, string serviceName)
		{
			if (shardingMetadata != null && shardingMetadata.ShardingType != 0)
			{
				return;
			}
			string text = "";
			string text2 = "";
			if (int.Parse(conn.ServerVersion.Split('.')[0]) < 19)
			{
				text = "SELECT GROUP_TYPE, SHARD_TYPE \n                                FROM LOCAL_CHUNK_TYPES";
				text2 = "SELECT SHARD_LEVEL, COL_IDX_IN_KEY, EFF_TYPE , CHARACTER_SET \n                                    FROM LOCAL_CHUNK_COLUMNS";
			}
			else
			{
				text = "SELECT GROUP_TYPE, SHARD_TYPE FROM LOCAL_CHUNK_TYPES  WHERE TABFAM_ID=(SELECT TABFAM_ID FROM LOCAL_TABLE_FAMILY_SERVICES WHERE SERVICE_NAME=:1)";
				text2 = "SELECT SHARD_LEVEL, COL_IDX_IN_KEY, EFF_TYPE, CHARACTER_SET FROM LOCAL_CHUNK_COLUMNS WHERE TABFAM_ID=(SELECT TABFAM_ID FROM LOCAL_TABLE_FAMILY_SERVICES WHERE SERVICE_NAME=:1)";
			}
			OracleCommand oracleCommand = null;
			OracleDataReader oracleDataReader = null;
			OracleCommand oracleCommand2 = null;
			OracleDataReader oracleDataReader2 = null;
			try
			{
				oracleCommand = new OracleCommand(text, conn);
				oracleCommand.Parameters.Add("prmServiceName", OracleDbType.Varchar2, serviceName, ParameterDirection.Input);
				oracleDataReader = oracleCommand.ExecuteReader();
				if (!oracleDataReader.Read())
				{
					return;
				}
				string value = (oracleDataReader.IsDBNull(0) ? "NONE" : oracleDataReader.GetString(0));
				ShardingType result = ShardingType.NONE;
				if (!Enum.TryParse<ShardingType>(value, ignoreCase: true, out result))
				{
					result = ShardingType.NONE;
				}
				string value2 = (oracleDataReader.IsDBNull(1) ? "NONE" : oracleDataReader.GetString(1));
				ShardingType result2 = ShardingType.NONE;
				if (!Enum.TryParse<ShardingType>(value2, ignoreCase: true, out result2))
				{
					result2 = ShardingType.NONE;
				}
				List<SubKeyMetadata> list = new List<SubKeyMetadata>();
				List<SubKeyMetadata> list2 = new List<SubKeyMetadata>();
				oracleCommand2 = new OracleCommand(text2, conn);
				oracleCommand2.Parameters.Add("prmServiceName", OracleDbType.Varchar2, serviceName, ParameterDirection.Input);
				oracleDataReader2 = oracleCommand2.ExecuteReader();
				while (oracleDataReader2.Read())
				{
					int @int = oracleDataReader2.GetInt32(0);
					int int2 = oracleDataReader2.GetInt32(1);
					int int3 = oracleDataReader2.GetInt32(2);
					SubKeyMetadata item = new SubKeyMetadata(charSet: (!oracleDataReader2.IsDBNull(3)) ? oracleDataReader2.GetInt32(3) : 0, index: int2, dataType: OracleShardingKeyImpl.getExternalType(int3));
					if (@int == ShardingMetadata.SUPER_SHARDING_KEY_LEVEL)
					{
						list2.Add(item);
					}
					else if (@int == ShardingMetadata.SHARDING_KEY_LEVEL)
					{
						list.Add(item);
					}
				}
				list.Sort();
				list2.Sort();
				shardingMetadata = new ShardingMetadata(result2, result, list, list2);
			}
			catch (InvalidOperationException)
			{
			}
			catch (Exception)
			{
			}
			finally
			{
				if (oracleDataReader != null)
				{
					oracleDataReader.Dispose();
					oracleDataReader = null;
				}
				if (oracleCommand != null)
				{
					oracleCommand.Dispose();
					oracleCommand = null;
				}
				if (oracleDataReader2 != null)
				{
					oracleDataReader2.Dispose();
					oracleDataReader2 = null;
				}
				if (oracleCommand2 != null)
				{
					oracleCommand2.Dispose();
					oracleCommand2 = null;
				}
			}
		}
	}
}
